package com.gjy.concurrency.future;

import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.*;

/**
 * @author 宫静雨
 * @version 1.0
 * @since 2023-01-12 14:29:34
 */
public class CompletableFutureT {
    private static final int processors = Runtime.getRuntime().availableProcessors();
    private static final ThreadPoolExecutor pool = new ThreadPoolExecutor(
            processors,
            processors * 2,
            1,
            TimeUnit.SECONDS,
            new ArrayBlockingQueue<>(processors * 10),
            Executors.defaultThreadFactory(),
            new ThreadPoolExecutor.AbortPolicy()
    );
    private static final Logger logger = LoggerFactory.getLogger(CompletableFutureT.class);

    @Test
    public void test4() throws ExecutionException, InterruptedException {
        CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(1);
                logger.error("抛出异常");
                throw new RuntimeException();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }).whenComplete((v, t) -> {
            logger.info("v: {}, t: {}", v, t);
        }).exceptionally(t -> {
            logger.info("t: {}", t.getMessage());
            return null;
        });
        Void unused = future.get();
        System.out.println("unused = " + unused);
    }

    @Test
    public void test3() throws ExecutionException, InterruptedException, TimeoutException {
        CompletableFuture<String> supplyAsync = CompletableFuture.supplyAsync(() -> {
            String s = "CompletableFuture supplyAsync";
            logger.info(s);
            return s;
        });

        CompletableFuture<String> supplyAsync2 = CompletableFuture.supplyAsync(() -> {
            String s = "CompletableFuture supplyAsync";
            logger.info(s);
            return s;
        }, pool);

        String s = supplyAsync.get(2, TimeUnit.SECONDS);
        System.out.println("s = " + s);
        String s2 = supplyAsync2.get(2, TimeUnit.SECONDS);
        System.out.println("s2 = " + s2);
    }

    @Test
    public void test2() throws Exception {

        CompletableFuture<Void> runAsync = CompletableFuture.runAsync(() -> {
            logger.info("Hello CompletableFuture");
        }, pool);

        runAsync.get(2, TimeUnit.SECONDS);
    }

    @Test
    public void test1() throws Exception {
        CompletableFuture<Void> runAsync = CompletableFuture.runAsync(() -> {
            logger.info("Hello CompletableFuture");
        });

        runAsync.get(2, TimeUnit.SECONDS);
    }
}
